package com.flame.application.initializer;

import jakarta.annotation.PostConstruct;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.jdbc.datasource.init.ScriptUtils;
import org.springframework.util.StringUtils;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Jflame
 * @version 1.0.0
 * @since 2025/8/14
 */
@Slf4j
@Getter
@Setter
@ConfigurationProperties(prefix = "database.initialization")
@Configuration
public class DatabaseInitializer {

    @jakarta.annotation.Resource
    private ResourceLoader resourceLoader;
    
    @jakarta.annotation.Resource
    private DataSource dataSource;

    private Mysql mysql = new Mysql();
    private Elasticsearch elasticsearch = new Elasticsearch();

    @Getter
    @Setter
    public static class Mysql {
        private Boolean enabled = false;
        private List<String> scriptLocations = new ArrayList<>();
    }

    @Getter
    @Setter
    public static class Elasticsearch {
        private Boolean enabled = false;
        private List<String> scriptLocations = new ArrayList<>();
    }

    @PostConstruct
    public void initialize() {
        log.info("开始数据库初始化...");
        if (Boolean.TRUE.equals(mysql.getEnabled())) {
            log.info("MySQL 初始化已启用，脚本位置: {}", mysql.getScriptLocations());
            executeSqlScripts(mysql.getScriptLocations());
        }
        if (Boolean.TRUE.equals(elasticsearch.getEnabled())) {
            log.info("Elasticsearch 初始化已启用，脚本位置: {}", elasticsearch.getScriptLocations());
        }
    }
    
    private void executeSqlScripts(List<String> scriptLocations) {
        for (String scriptLocation : scriptLocations) {
            try {
                Resource resource = loadResource(scriptLocation);
                if (resource.exists()) {
                    executeScript(resource);
                } else {
                    log.error("找不到SQL脚本文件: {}", scriptLocation);
                }
            } catch (Exception e) {
                log.error("执行SQL脚本失败: {}", scriptLocation, e);
            }
        }
    }
    
    private Resource loadResource(String location) {
        // 输入验证
        if (!StringUtils.hasText(location)) {
            throw new IllegalArgumentException("资源路径不能为空");
        }
        
        // 处理不同类型的路径
        if (location.startsWith("classpath:")) {
            // classpath路径
            return resourceLoader.getResource(location);
        } else if (location.startsWith("file:")) {
            // 显式文件路径
            return resourceLoader.getResource(location);
        } else if (location.startsWith("/")) {
            // Unix/Linux绝对路径
            return resourceLoader.getResource("file:" + location);
        } else if (location.length() > 2 && 
                  ((location.charAt(1) == ':' && (location.charAt(2) == '\\' || location.charAt(2) == '/')))) {
            // Windows绝对路径 (例如 C:\path\to\file)
            return resourceLoader.getResource("file:" + location);
        } else {
            // 相对路径，相对于classpath
            return resourceLoader.getResource("classpath:" + location);
        }
    }
    
    private void executeScript(Resource resource) throws SQLException {
        try (Connection connection = dataSource.getConnection()) {
            log.info("正在执行SQL脚本: {}", resource.getDescription());
            ScriptUtils.executeSqlScript(connection, resource);
            log.info("SQL脚本执行完成: {}", resource.getDescription());
        } catch (Exception e) {
            log.error("执行SQL脚本出错: {}", resource.getDescription(), e);
            throw e;
        }
    }
}
